/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.jms;

import java.util.Vector;

import javax.jms.Connection;
import javax.jms.ConnectionMetaData;
import javax.jms.ExceptionListener;
import javax.jms.InvalidClientIDException;
import javax.jms.JMSException;

/** This class implements the JMS connection. 
    @author Shrideep Pallickara
    $Revision$
    $Date$
*/

public class JmsConnection implements Connection {

  /** These variable indicate the state of the connection */
  private boolean stopped = true; /** Connection is in the start/stop state */ 
  private boolean closed = false; /** Connection is closed? */
  
  /** This is the client ID. This needs to be initialized when the connection
      is created. Attempts to set it otherwise should result in exceptions */
  private String clientID=null;

  /** Every connection needs to maintain, one (and no more) exception listener
      that is notified of exceptions that occur. */
  private ExceptionListener exceptionListener;
  
  /** The immutable Connection Data */
  private static final JmsConnectionMetaData jmsConnectionMetaData =
  new JmsConnectionMetaData();
  
  /** This vector maintains a list of the sessions that are registered to
      this connection. */
  private Vector sessions;
   
  
  public JmsConnection() {
    sessions = new Vector();
  }
  
  /** Gets the client identifier for this connection.
      @return the unique client identifier
      @exception JMSException if the JMS provider fails to return
      the client ID for this connection due to some internal error.
  **/
  public String getClientID() throws JMSException {
    if (closed) {
      throw new javax.jms.IllegalStateException("Trying to get the ClientID" +
						" from a closed Connection");
    }
    return clientID;
  }
  
  /** Sets the client identifier for this connection.
      @param clientID the unique client identifier
      @exception JMSException if the JMS provider fails to set the client ID 
      for this connection due to some internal error.
      @exception InvalidClientIDException if the JMS client specifies an
      invalid or duplicate client ID.
      @exception javax.jms.IllegalStateException if the JMS client attempts to
      set a connection's client ID at the wrong time or when it has been 
      administratively configured.
  */
  public void setClientID(String clientID) throws JMSException {
    if (closed) {
      throw 
	new javax.jms.IllegalStateException("Trying to set the ClientID on " +
					    " a closed Connection");
    }
    /** The clientID needs to be setup only during initialization. Any other
	attempts at later times throw exceptions */
    throw new JMSException("The ClientID can be initialized only once");
  }
  
  /** Gets the metadata for this connection.
      @return the connection metadata
      @exception JMSException if the JMS provider fails to get the 
      connection metadata for this connection.
      @see javax.jms.ConnectionMetaData
  */
  public ConnectionMetaData getMetaData() throws JMSException {
    if (closed) {
      throw 
	new javax.jms.IllegalStateException("Querying connection MetaData on "
					    + "a closed Connection");
    }
    return jmsConnectionMetaData;
  }
  
  /**
     Gets the <CODE>ExceptionListener</CODE> object for this connection.
     @return the <CODE>ExceptionListener</CODE> for this connection
     @exception JMSException if the JMS provider fails to get the 
     <CODE>ExceptionListener</CODE> for this connection.
  */
  public ExceptionListener getExceptionListener() throws JMSException {
    if (closed) {
      throw 
	new javax.jms.IllegalStateException("Querying exception listener on " +
					    " a closed Connection");
    }
    return exceptionListener;
  }
  
  /** Sets an exception listener for this connection.
      @param listener the exception listener
      @exception JMSException if the JMS provider fails to set the exception 
      listener for this connection.
  */
  public void setExceptionListener(ExceptionListener listener) 
    throws JMSException {
    if (closed) {
      throw 
	new javax.jms.IllegalStateException("Setting exception listener on " +
					    " a closed Connection");
    }
    exceptionListener = listener;
  }
  
  /** If there is a registered exception listener, this method notifies the
      exception listener if there are any exceptions that take place. If the
      listener is null the exception is simply ignored 
      @param exception The exception that has occured. 
      
  */
  public void notifyExceptionListener(JMSException exception) {
    if (JmsDebugFlags.JmsConnection_Debug)
      System.out.println(exception);
    if (exceptionListener != null) 
      exceptionListener.onException(exception);
  }
  
  /** 
      Starts (or restarts) a connection's delivery of incoming messages.
      A call to <CODE>start</CODE> on a connection that has already been
      started is ignored.
      @exception JMSException if the JMS provider fails to start
      message delivery due to some internal error.
      @see javax.jms.Connection#stop
  */
  public void start() throws JMSException {
    if (closed)
      throw 
	new javax.jms.IllegalStateException("Peforming the start operation on"
					    + " a closed Connection");
    if (!stopped) {
      /* No need to start any sessions, since they are already started */
      return;
    }
    
    /*********** Start every session that is registered to this connection */
    for (int i=0; i < sessions.size(); i++) {
      ((JmsSession)sessions.elementAt(i)).startSession();
    }
    stopped = false;
  }
  
  /** Temporarily stops a connection's delivery of incoming messages.
      Delivery can be restarted using the connection's <CODE>start</CODE>
      method. When the connection is stopped, delivery to all the connection's
      message consumers is inhibited: synchronous receives block, and messages
      are not delivered to message listeners.
      
      @exception JMSException if the JMS provider fails to stop message 
      delivery due to some internal error.
      @see javax.jms.Connection#start
  */
  public void stop() throws JMSException {
    if (closed)
      throw 
	new javax.jms.IllegalStateException("Peforming the stop operation on" +
					    " a closed Connection");
    if (stopped) {
      /* No need to stop any sessions, since they are already stopped */
      return;
    }
    
    /**** Stop every session that is registered to this connection ****/
    for (int i=0; i < sessions.size(); i++) {
      ((JmsSession)sessions.elementAt(i)).stopSession();
    }
    stopped = true;
  }
  
  
  /** Closes the connection.
      @exception JMSException if the JMS provider fails to close the
      connection due to some internal error. For example, a failure to release
      resources or to close a socket connection can cause this exception to 
      be thrown.
  */
  public  void close() throws JMSException {
    if (closed) {
      /** No need to do anything further, simply return */
      return;
    }
      
    if (!stopped) {
      /** Stop all the sessions prior to closing them */
      for (int i=0; i < sessions.size(); i++) {
	((JmsSession)sessions.elementAt(i)).stopSession();
      }
      stopped = true;
    }/*end-if */
    
    /** Proceed to close all sessions */
    for (int i=0; i < sessions.size(); i++) {
      ((JmsSession)sessions.elementAt(i)).close();
    }
    /** Clear the set of managed sessions */
    sessions.clear();

    closed = true;
  }
  
  
  public void addToListOfManagedSessions(JmsSession session) {
    sessions.addElement(session);
  }
   
}




